﻿#include "Dx2RootSignatureManager.h"



void Dx2RootSignatureManager::BuildRootSignature(ID3D12Device* device)
{
    BuildDefaultRootSignature(device);
    BuildWavesRootSignature(device);
    BuildVecAddRootSignature(device);
    BuildBlurRootSignature(device);
    BuildCompositionRootSignature(device);
    BuildTessellationRootSignature(device);
}

Microsoft::WRL::ComPtr<ID3D12RootSignature> Dx2RootSignatureManager::GetRootSignature(RootSignatureType type)
{
    Microsoft::WRL::ComPtr<ID3D12RootSignature> rootSignature = nullptr;

    if(mRootSignatures.find(type) != mRootSignatures.end())
    {
        rootSignature = mRootSignatures[type];
    }

    return rootSignature;
}

void Dx2RootSignatureManager::BuildDefaultRootSignature(ID3D12Device* device)
{
    assert(device != nullptr);
    
    CD3DX12_DESCRIPTOR_RANGE texTable;
    texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,0);

    CD3DX12_DESCRIPTOR_RANGE displacementMapTable;
    displacementMapTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,1);
	
    CD3DX12_ROOT_PARAMETER slotRootParameter[5];

    slotRootParameter[0].InitAsDescriptorTable(1,&texTable,D3D12_SHADER_VISIBILITY_ALL);
    slotRootParameter[1].InitAsConstantBufferView(0);
    slotRootParameter[2].InitAsConstantBufferView(1);
    slotRootParameter[3].InitAsConstantBufferView(2);
    slotRootParameter[4].InitAsDescriptorTable(1,&displacementMapTable,D3D12_SHADER_VISIBILITY_ALL);
	
    auto staticSamplers = GetStaticSamplers();

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5,slotRootParameter,
        (UINT)staticSamplers.size(),staticSamplers.data(),
        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;

    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc,D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(),errorBlob.GetAddressOf());

    if(errorBlob !=nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;

    ThrowIfFailed(device->CreateRootSignature(0,serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),IID_PPV_ARGS(RootSignature.GetAddressOf())));
    

   mRootSignatures[RootSignatureType::Default] = RootSignature;
}

void Dx2RootSignatureManager::BuildWavesRootSignature(ID3D12Device* device)
{
    CD3DX12_DESCRIPTOR_RANGE uavTable0;
    uavTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV,1,0);

    CD3DX12_DESCRIPTOR_RANGE uavTable1;
    uavTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV,1,1);

    CD3DX12_DESCRIPTOR_RANGE uavTable2;
    uavTable2.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV,1,2);

    CD3DX12_ROOT_PARAMETER slotRootParameter[4];
    slotRootParameter[0].InitAsConstants(6,0);
    slotRootParameter[1].InitAsDescriptorTable(1,&uavTable0);
    slotRootParameter[2].InitAsDescriptorTable(1,&uavTable1);
    slotRootParameter[3].InitAsDescriptorTable(1,&uavTable2);

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4,slotRootParameter,
    0,nullptr,
    D3D12_ROOT_SIGNATURE_FLAG_NONE);

    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;

    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc,D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(),errorBlob.GetAddressOf());

    if(errorBlob !=nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;

    ThrowIfFailed(device->CreateRootSignature(0,serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),IID_PPV_ARGS(RootSignature.GetAddressOf())));

    mRootSignatures[RootSignatureType::Wave] = RootSignature;
}

void Dx2RootSignatureManager::BuildVecAddRootSignature(ID3D12Device* device)
{
    CD3DX12_ROOT_PARAMETER slotRootParameter[3];

    slotRootParameter[0].InitAsShaderResourceView(0);
    slotRootParameter[1].InitAsShaderResourceView(1);
    slotRootParameter[2].InitAsUnorderedAccessView(0);

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3,slotRootParameter,
        0,nullptr,D3D12_ROOT_SIGNATURE_FLAG_NONE);

    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;

    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc,D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(),errorBlob.GetAddressOf());

    if(errorBlob !=nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);
	

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;
    ThrowIfFailed(device->CreateRootSignature(0,serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),IID_PPV_ARGS(RootSignature.GetAddressOf())));

    mRootSignatures[RootSignatureType::VecAndAdd] = RootSignature;
}

void Dx2RootSignatureManager::BuildBlurRootSignature(ID3D12Device* device)
{
    CD3DX12_ROOT_PARAMETER slotRootParameter[3];

    CD3DX12_DESCRIPTOR_RANGE srvTable;
    srvTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,0);

    CD3DX12_DESCRIPTOR_RANGE uavTable;
    uavTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV,1,0);

    slotRootParameter[0].InitAsConstants(12,0);
    slotRootParameter[1].InitAsDescriptorTable(1,&srvTable);
    slotRootParameter[2].InitAsDescriptorTable(1,&uavTable);

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3,slotRootParameter,
        0,nullptr,D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

    // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());

    if(errorBlob != nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;
    ThrowIfFailed(device->CreateRootSignature(
        0,
        serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),
        IID_PPV_ARGS(RootSignature.GetAddressOf())));

    mRootSignatures[RootSignatureType::Blur] = RootSignature;
}

void Dx2RootSignatureManager::BuildCompositionRootSignature(ID3D12Device* device)
{
    CD3DX12_DESCRIPTOR_RANGE srvTable0;
    srvTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,0);

    CD3DX12_DESCRIPTOR_RANGE srvTable1;
    srvTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,1);

    CD3DX12_DESCRIPTOR_RANGE uavTable0;
    uavTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV,1,0);

    CD3DX12_ROOT_PARAMETER slotRootParameter[3];

    slotRootParameter[0].InitAsDescriptorTable(1,&srvTable0);
    slotRootParameter[1].InitAsDescriptorTable(1,&srvTable1);
    slotRootParameter[2].InitAsDescriptorTable(1, &uavTable0);

    auto staticSampler = GetStaticSamplers();

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3,slotRootParameter,
        (UINT)staticSampler.size(),staticSampler.data(),D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());

    if(errorBlob != nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;

    ThrowIfFailed(device->CreateRootSignature(
        0,
        serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),
        IID_PPV_ARGS(RootSignature.GetAddressOf())));

    mRootSignatures[RootSignatureType::Composite] = RootSignature;
}

void Dx2RootSignatureManager::BuildTessellationRootSignature(ID3D12Device* device)
{
    CD3DX12_DESCRIPTOR_RANGE texTable;
    texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV,1,0);

    CD3DX12_ROOT_PARAMETER slotRootParameter[4];

    slotRootParameter[0].InitAsDescriptorTable(1,&texTable,D3D12_SHADER_VISIBILITY_PIXEL);
    slotRootParameter[1].InitAsConstantBufferView(0);
    slotRootParameter[2].InitAsConstantBufferView(1);
    slotRootParameter[3].InitAsConstantBufferView(3);

    auto staticSample = GetStaticSamplers();

    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
        (UINT)staticSample.size(), staticSample.data(),
        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

    Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());

    if(errorBlob != nullptr)
    {
        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
    }
    ThrowIfFailed(hr);

    Microsoft::WRL::ComPtr<ID3D12RootSignature> RootSignature;
    
    ThrowIfFailed(device->CreateRootSignature(
        0,
        serializedRootSig->GetBufferPointer(),
        serializedRootSig->GetBufferSize(),
        IID_PPV_ARGS(RootSignature.GetAddressOf())));

    mRootSignatures[RootSignatureType::Tessellation] = RootSignature;
}

